home *** CD-ROM | disk | FTP | other *** search
- .co This is the source form of the release notes for Gofer 2.30
- .co
- .co Mark P Jones June 1994
- .co-------------------------------------------------------------------|
- .>release.230
- -----------------------------------------------------------------------
- __________ __________ __________ __________ ________
- / _______/ / ____ / / _______/ / _______/ / ____ \
- / / _____ / / / / / /______ / /______ / /___/ /
- / / /_ / / / / / / _______/ / _______/ / __ __/
- / /___/ / / /___/ / / / / /______ / / \ \
- /_________/ /_________/ /__/ /_________/ /__/ \__\
-
- Functional programming environment, Version 2.30
-
- Copyright Mark P Jones 1994. This release is subject to the same
- conditions of use and distribution as previous versions, documented
- in src/goferite.h and in the main user manual.
-
- Release notes
- -----------------------------------------------------------------------
-
- This document is intended to be used as a supplement to the original
- user manual ``An introduction to Gofer version 2.20'' and release
- notes for Gofer 2.21 and Gofer 2.28. These notes replace the
- preliminary version distributed with Gofer 2.30.
-
- ACKNOWLEDGMENTS:
- A lot of people have contributed to the development of Gofer 2.30a
- with their support, encouragement, suggestions, comments and bug
- reports. There are a lot of people to thank:
-
- Jim Blandy Jonathan Bowen Rodney Brown
- Nick Chapman Derek Charleston Stuart Clayman
- Terry Dineen Luc Duponcheel Dirk Dussart
- Sebastian Egner Stephen Eldridge Jeroen Fokker
- Jeff Fried Andy Gill Michial Gunter
- Kevin Hammond Daniel Harris Barney Hilken
- Steve Hill Ian Holyer Richard Jones
- Fumiaki Kamiya Eak Khoon Hiroyuki Matsuda
- Sava Mintchev Torben Mogensen Dirk Nehring
- Chin Wei Ngan Kurt Olender Palle Nielsen
- Ian Poole Bambang Prastowo Jaan Priisalu
- Giuliano Procida Jerry Prothero Laurenz Pruessner
- Niklas R\"ojemo Kristoffer Rose Bernhard Rumpe
- David Rushall Carsten Schultz Viren Shah
- Dave Sherratt Guy Steele Jr. Donald Smith
- Matthew Smith Michael Stout Bernard Sufrin
- Peter Thiemann Stephen Thomas Bert Thompson
- Ignacio Trejos-Zelaya Goeran Uddeborg Robin Watts
- Gavin Wraith David Wright Isii Yuuitirou
-
- This also includes the names of people who sent comments and bug
- reports after the release of version 2.28 and who may not have been
- credited in previous release notes. The list probably isn't complete,
- and I apologize if I have inadvertently left your name out.
-
- Enjoy! jones-mark@cs.yale.edu (Until mid-July 1994)
- Mark mpj@cs.nott.ac.uk (From Sept/Oct 1994)
- .pa
- .ti Release Notes v2.30
- .co-------------------------------------------------------------------|
- .ST 1. MINOR ENHANCEMENTS AND BUGFIXES
-
- The following sections list the minor enhancements and bugfixes that
- have been made to Gofer since the release of version 2.28. More
- significant changes are described in Section 2.
-
-
- .ST 1.1 Enhancements
- -----------------
- o A new command, :gc, has been added, making it possible to force the
- interpreter to carry out a garbage collection.
-
- o The infamous `too many variables in type checker' message that has
- caused problems with some programs, particularly machine generated
- Gofer scripts like the parsers produced by Ratatosk, should now be
- a thing of the past. The message may still appear when running
- such programs on smaller machines where the amount of free memory
- available for such things is very limited.
-
- o It is now possible to compile Gofer without support for old style
- Dialogue based I/O and, independently, without support for (n+k)
- and (c*n) patterns. You may take this as a hint that these
- features may not be supported in future versions, although no firm
- decisions have been made just yet.
-
- o As a convenience, the parser allows constructor expressions of
- the form (t ->) as an abbreviation for ((->) t).
-
- o Tuple patterns (with irrefutable components) are now treated as
- irrefutable patterns, but without changing the previous lifted
- semantics. This is marginallly more efficient. It also means
- that it is no longer necessary to use ~ for generators of the form
- (x,y) <- expr in monad comprehensions, too avoid restricting the
- enclosing comprehension to monads with a zero.
-
- o Type expressions appearing in primitive declarations may now
- include synonyms, classes etc. defined in the same script.
-
- o Other minor tweaks and improvements.
-
-
- .ST 1.2 Bug fixes
- --------------
- Nobody really likes to dwell on bugs, especially when they have been
- eliminated. But for those of you who want to know, here is a summary of
- the bugs discovered and fixed in Gofer 2.30:
-
- o Test programs apr*.gs that were included in previous distributions
- are no longer included in the src directory. These programs were
- intended only for quick tests, not for public distribution. The
- fact that some of the test programs (intentionally) caused errors,
- was a source of unnecessary concern for some since the expected
- behaviour was not documented.
-
- o Some minor fixes to the parser/grammar to give better error
- messages.
-
- o Fixed problems with the :edit command on some machines,
- particularly noticeable on the RISCOS version.
-
- o Large integer constants that are outside the range for Int
- values are no longer implicitly coerced to type Float.
-
- o The implementations of assignment in the LAMBDAVAR and LAMBDANU
- extensions, and the implementation of the system primitive for
- LAMBDANU contained subtle bugs that have now been fixed. Note
- however that these extensions are now regarded as obsolete, and
- will probably not be supported in future versions. (LAMBDAVAR and
- LAMBDANU where never formally included as an official feature of
- Gofer anyway.)
-
- o Infix data constructors can now be used in a datatype definition
- such as:
-
- data Tree a = Empty | Tree a `Fork` Tree a
-
- o A very subtle bug in the unification algorithm has been fixed.
-
- o Some bugs in mildly complicated examples involving pattern
- matching of integer constants and singleton lists have been
- fixed.
-
- o Fixed some small problems with a couple of the demonstration
- programs.
-
- o Modified prelude definitions of the index function (in class Ix)
- to include a bounds check.
-
- o Other minor bug fixes and tweaks.
-
- Someone is bound to find a new one within hours of the release of 2.30,
- if past experience is anything to go by. If that someone is you,
- please let me know!
-
-
- .co-------------------------------------------------------------------|
- .ST 2. LANGUAGE DIFFERENCES
-
- This section outlines a number of more substantial extensions that are
- supported in Gofer 2.30. One of the most important motivations for
- some of these extensions, and part of an ongoing process, is to provide
- greater compatibility with standard Haskell.
-
-
- .ST 2.1 Contexts in datatype definitions
- -------------------------------------
- For greater compatibility with Haskell, it is now possible to include
- contexts in datatype definitions. These are treated in exactly the
- same way as in Haskell. For example, the only effect of using a
- context in the datatype definition:
-
- data Eq a => Set a = NilSet | ConsSet a (Set a)
-
- is to treat the ConsSet constructor function as having type:
-
- ConsSet :: Eq a => a -> Set a -> Set a
-
- See Section 4.2.1 of the Haskell report, version 1.2, for further
- details.
-
-
- .ST 2.2 Contexts in member function types
- --------------------------------------
- For greater compatibility with Haskell, it is now possible to include
- contexts in the type of member function definitions in a class
- specification. For example, you can now try out the class definition
- for pseudo monads given in the Yale Research Report YALEU/DCS/RR-1004
- entitled `Composing Monads' by myself and Luc Duponcheel:
-
- class Premonad m => Pseudomonad m where
- pbind :: Monad m => p a -> (a -> m (p b)) -> m (p b)
-
- Unlike Haskell, Gofer does not make the restriction that the additional
- constraints on the types of the member functions should not mention any
- of the types in the first line of the class declaration. This appears
- to have been a consequence of the formal system underlying the original
- theoretical work on type classes by Blott. For the qualified type
- system that is used as a basis for Gofer, such restrictions are
- unnecessary, although one might argue that they should be retained on
- stylistic grounds ...
-
- See Section 4.3.1 of the Haskell report, version 1.2, for further
- details.
-
-
- .ST 2.3 Haskell arrays
- -------------------
- For closer compatibility with Haskell, Gofer now supports a built-in
- implementation of Haskell style arrays. To include support for these
- arrays, Gofer must be compiled with the HASKELL_ARRAYS flag set to 1.
- This is the default for all but the very smallest PC version of Gofer.
-
- The implementation includes is based on new primitive datatype:
-
- data Array a b
-
- The array primitives are not currently incorporated into any of the
- preludes supplied with Gofer. However a separate script file,
- array.gs, is included in the same directory with the following
- interface:
-
- data Assoc a b = a := b deriving (Eq, Ord, Text)
-
- array :: Ix a => (a,a) -> [Assoc a b] -> Array a b
- listArray :: Ix a => (a,a) -> [b] -> Array a b
- (!) :: Ix a => Array a b -> a -> b
- bounds :: Ix a => Array a b -> (a,a)
- indices :: Ix a => Array a b -> [a]
- elems :: Ix a => Array a b -> [b]
- assocs :: Ix a => Array a b -> [Assoc a b]
- accumArray :: Ix a => (b -> c -> b) -> b -> (a,a)
- -> [Assoc a c] -> Array a b
- (//) :: Ix a => Array a b -> [Assoc a b] -> Array a b
- accum :: Ix a => (b -> c -> b) -> Array a b
- -> [Assoc a c] -> Array a b
- amap :: Ix a => (b -> c) -> Array a b -> Array a c
- ixmap :: (Ix a, Ix b) => (a,a) -> (a -> b)
- -> Array b c -> Array a c
-
- instance (Ix a, Eq [Assoc a b]) => Eq (Array a b)
- instance (Ix a, Ord [Assoc a b]) => Ord (Array a b)
- instance (Ix a, Text (a,a), Text [Assoc a b])
- => Text (Array a b)
-
- instance (Ix a, Ix b) => Ix (a,b)
- rangeSize :: (Ix a) => (a,a) -> Int
-
- For example, to use these primitives in a Gofer session, just include
- array.gs as the first file that you load, or as the one of the first
- file names in a project file.
-
- Arrays, and the primitives above are supported in both the interpreter
- and the compiler. Because of restrictions in memory management, the
- current implementation does not provide true O(1) lookup/indexing in
- the interpreter or the compiler using the markscan garbage collector.
- True O(1) access is supported when the twospace collector is used for
- compiled programs.
-
- See Section 6.9 of the Haskell report, version 1.2, for further details
- about the use of arrays and the primitives described above. Please
- bear in mind that the current implementation is still preliminary, and
- may contain bugs. Please let me know if you encounter any problems
- with it! A few short demo programs are included in demos/arrayEx.gs.
-
-
- .ST 2.4 Monadic I/O
- ----------------
- A preliminary implementation of the monadic I/O is supported, built on
- top of the framework for lazy functional state threads that has been
- proposed by John Launchbury and Simon Peyton Jones (PLDI '94). The
- details of monadic I/O can be expected to change in future releases as
- a new standard for monadic I/O is established. For the time being, the
- primitives described here will be of most interest to those looking to
- experiment with simple monadic I/O and the Launchbury/Peyton Jones
- system. To include support for monadic I/O, Gofer must be compiled
- with the IO_MONAD flag set to 1. This is the default for all but the
- very smallest PC version of Gofer.
-
- The current implementation provides several new primitive types:
-
- data ST s a -- lazy state threads monad
- data World -- representation of `the world'
- type IO = ST World -- the I/O monad proper
- data MutVar s a -- a mutable variable
-
- An interface to monadic I/O can be obtained by loading the file
- iomonad.gs which may be found in the same directory as the prelude
- files. This provides the following operations:
-
- returnST :: a -> ST s a
- thenST :: ST s a -> (a -> ST s b) -> ST s b
- thenST_ :: ST s () -> ST s b -> ST s b
- seqST :: [ST s ()] -> ST s ()
-
- newVar :: a -> ST s (MutVar s a)
- readVar :: MutVar s a -> ST s a
- writeVar :: MutVar s a -> a -> ST s ()
- mutvarEq :: MutVar s a -> MutVar s a -> Bool
-
- instance Eq (MutVar s a)
-
- getch :: IO Char
- getchar :: IO Char
- putchar :: Char -> IO ()
- putString :: String -> IO ()
- thenIO :: ST s a -> (a -> ST s b) -> ST s b
- interleaveST :: ST s a -> ST s a
-
- There is also a built-in special form, runST expr, which is typed using
- the rule:
-
- expr :: forall s. ST s a (s not appearing in a)
- ------------------------
- runST expr :: a
-
- This special form is used for encapsulating state based computations
- within a purely functional program. See references below for more
- details.
-
- If the version of Gofer being used also includes support for arrays, as
- described above, you can also use the definitions in ioarray.gs to
- support monadic array operations:
-
- newArr :: Ix a => (a,a) -> b -> ST s (MutArr s a b)
- readArr :: Ix a => MutArr s a b -> a -> ST s b
- writeArr :: Ix a => MutArr s a b -> a -> b -> ST s ()
- freezeArr :: Ix a => MutArr s a b -> ST s (Array a b)
-
- Some sample programs using the functions described here may be found in
- the demos/IO directory. For further details about monadic I/O, please
- consult the papers:
-
- Imperative Functional Programming, S.L. Peyton Jones and
- P. Wadler, POPL '93.
-
- Lazy Functional State Threads, J. Launchbury and S.L. Peyton
- Jones, PLDI '94.
-
- See also:
-
- Lazy depth-first search and linear graph algorithms in
- Haskell, D. King and J. Launchbury, 1993.
-
- for some very nice applications of lazy functional state threads. All
- of these papers are currently available by anonymous ftp from the
- University of Glasgow, ftp.dcs.glasgow.ac.uk.
-
- Monadic I/O as described above is supported in both the Gofer
- interpreter and compiler. No special optimizations are used in the
- current implementation which should still be treated as preliminary,
- and may contain bugs. Please let me know if you encounter any problems
- with it!
-
-
- .ST 2.5 Trace primitive
- --------------------
- A simple trace function, inspired by the original implementation in
- LML, can now be accessed by including the primitive definition:
-
- primitive trace "primTrace" :: String -> a -> a
-
- in a Gofer script. When called, trace prints the string in its first
- argument, then returns the second argument as its result. The trace
- function is not referentially transparent, and should only be used for
- debugging, or monitoring execution. That is why it is not included in
- any of the preludes. Be warned also that, unless you understand
- something about the way that Gofer programs are actually executed,
- results obtained using trace may be rather confusing.
-
- Because of it's intended use, the trace primitive is not supported
- by the Gofer compiler, gofc. It is however possible to `hack' in
- a version of trace for gofc using the external function call
- mechanism described below with the following C program:
-
- #include <stdio.h>
- #include "/usr/local/lib/Gofer/gofc.h"
-
- #define emptyList mkCfun(0)
-
- extern Cell primTrace(str,val)
- Cell str, val; {
- eval(str);
- while (whnf!=emptyList) {
- eval(pop());
- putchar(charOf(whnf));
- eval(pop());
- }
- fflush(stdout);
- return val; }
-
- See Section 2.7 below for further details.
-
-
-
- .ST 2.6 Constructor synonyms
- -------------------------
- Type synonym definitions have been generalized to allow arbitrary
- constructor synonyms such as:
-
- type List = []
- type Function = (->)
- type Infer = StateM Int Error
-
- Previously, it was assumed that both the constructors on the left and
- right hand sides were types, i.e. constructors of kind *. This
- restriction has now been lifted, although both sides are still required
- to have the same kind. However, the restriction that all arguments to
- a synonym must be given is still imposed.
-
-
- .ST 2.7 External function calls
- ----------------------------
- The Gofc compiler, translating Gofer programs to C provides a simple
- external function calling mechanism.
-
- External functions are specified using a primitive declaration of the
- form:
-
- primitive foo "bar" :: a1 -> a2 -> a3 -> ... -> an -> r
-
- where foo is the Gofer name for the function, bar is the name of the
- corresponding C function (which must not be a string referring to one
- of the built in primitives ... if you avoid the `prim' prefix, this
- should not be a problem), the ai are the argument types, and r is the
- result type. Arguments of type Int, Bool, Char and Float are evaluated
- before the bar function is invoked, and their results passed to bar in
- parameters of suitable types. All other values are passed as
- unevaluated Cell values. (Special treatment is also provided for
- arrays, mutable variables, and mutable arrays for versions of Gofer
- that support these facilities.)
-
- Results of type Int, Bool, Char and Float returned from an external
- function are automatically converted to suitable representations for
- Gofer. Values of any other type should be passed back as Cell values
- by the C code for the external function.
-
- A result type of the form IO r should be used for external functions
- that may have some side effects. A result type of the form IO () can
- be used to call a function that does not return any useful value and is
- executed only for its effect.
-
- Here is a simple example using the external function mechanism. It
- involves the following short Gofer and C programs:
-
- (gix1.gs): primitive howdy "sayHello" :: Int -> IO ()
-
- main = howdy (length (filter even [1..5]))
-
- (cix1.c): #include <stdio.h>
- #include "gofc.h"
-
- Void sayHello(i)
- Int i; {
- while (i-- > 0)
- printf("hello, world\n");
- }
-
- First, we compile gix1.gs to get a C program gix1.c:
-
- machine% gofc gix1.gs
- Gofer->C Version 1.02 (2.30) ...
-
- Reading script file "/usr/local/lib/Gofer/standard.prelude":
- Reading script file "gix1.gs":
-
- Writing C output file "gix1.c":
- [Leaving Gofer->C]
-
- Now we compile the C programs, and link them into a single executable
- file, ix1:
-
- machine% cc -O -o ix1 gix1.c cix1.c runtime.o
-
- Finally, we get to run the program:
-
- machine% ix1
- hello, world
- hello, world
-
- Note that the external function call mechanism described here cannot be
- used in the Gofer interpreter. The external function call mechanism is
- a prototype only. It should also be emphasized that we do not, in
- general, regard the Gofc compiler as suitable for serious applications
- development. If you want to do something along those lines, try one of
- the full Haskell systems available (e.g. the Lisp or C interfaces for
- Yale Haskell, or the C interface for Glasgow Haskell).
-
-
- .ST 2.8 The do notation
- --------------------
- Gofer 2.30 supports a new, experimental syntax for monad comprehensions
- which we will refer to as `do {...} notation'. The do notation is only
- supported if the system is compiled with the DO_COMPS flag in prelude.h
- set to to 1, and the DO_COMPS section of parser.y included. See the
- comments in these files for further details.
-
- The do notation is useful for monadic programming, and requires the
- cc.prelude, and uses the following syntax:
-
- <expr> ::= do "{" <dquals> <expr> "}" -- uses layout rule
-
- <dquals> ::= {<dqual> ;}
-
- <dqual> ::= <pat> <- <expr> -- generator
- | <expr> -- command
- | let "{" decls "}" -- local definitions
- | if <expr> -- guard
-
- With this notation, a guard is written as if <expr>, while a single
- expression of the form <expr> is treated as a command, i.e. a generator
- of the form _ <- <expr>. For example, a general version of the filter
- function can be defined as:
-
- myFilter :: Monad0 m => (a -> Bool) -> m a -> m a
- myFilter p xs = do x <- xs
- if p x
- result x
-
- If you prefer, this can be written as follows, using explicit layout:
-
- myFilter p xs = do { x <- xs;
- if p x;
- result x
- }
-
- In standard comprehension notation, this would be written:
-
- myFilter p xs = [ x | x <- xs, p x ]
-
- Perhaps the most significant difference between these two examples is
- the fact that the call to result must be written explicitly in the
- first case. In fact, if the comprehension is interpreted in a monad,
- m, then any expression of type (m a) can be used as the final
- expression in a do comprehension. This is useful for describing `tail
- recursive' procedures. For example, compare:
-
- echo' = do c <- getchar
- if c==EOF
- then result ()
- else do putchar c
- echo'
-
- with:
-
- echo' = [ () | c <- getchar,
- () <- if c==EOF then result ()
- else [ () | _ <- putchar c,
- () <- echo' ] ]
-
- It is, of course, a matter of personal opinion which of these you
- prefer. The intention of do notation is to provide a more attractive
- syntax for monadic programming, to be compared with programs using
- `bind` in which the example above would be written:
-
- echo' = getchar `bind` \c ->
- if c==EOF then result ()
- else putchar c `bind` \_ ->
- echo'
-
- See which notation you prefer for practical programming, and let me
- know!
-
- .co-------------------------------------------------------------------|
- .ST 3. THE IMPLEMENTATION OF GOFER
-
- For those interested in the actual implementation of Gofer, there is
- a (relatively new) technical report available that describes the
- implementation of Gofer 2.30:
-
- The implementation of the Gofer functional programming system
- Mark P. Jones
- Research Report YALEU/DCS/RR-1030
- Yale University, Department of Computer Science,
- May 1994.
-
- Copies of this report are currently available by anonymous ftp from
- nebula.cs.yale.edu in the directory pub/yale-fp/reports, together
- with a number of other recent reports by members of the Yale Haskell
- project.
-
-
- .co-------------------------------------------------------------------|
-